package com.zf.xxljob.job;

import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;

/**
 * 注意点：
 * - 从 xxl-job 2.2.0版本开始，移除@JobHandler注解，只能使用 在Bean的方法上添加 @XxlJob(value="jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法") 注解的方式定义job。
 * - 执行日志：需要通过 "XxlJobHelper.log" 打印执行日志到 xxl-job-admin 控制台。
 * - 只能通过 XxlJobHelper.getJobParam() 方式获取传参，其他方式无法获取。
 * - JOB执行的结果默认是成功的，与返回值没有关系、返回值没有意义。可以手动调用 XxlJobHelper.handleFail 或 XxlJobHelper.handleSuccess 设置为失败或者成功。
 */
@Slf4j
@Component
public class XxlJobSample {

    /**
     * 定义一个定时任务
     * XxlJob("firstMethodJob")注解指定了job的名称是 firstMethodJob
     */
    @XxlJob("firstMethodJob")
    public void firstMethodJob() {
        // XxlJobHelper.log 记录日志到 xxl-job-admin 控制台，可以在控制台调度日志页面查看
        XxlJobHelper.log("---------firstMethodJob定时任务执行成功--------");
        // 打印本地日志
        log.info("---------firstMethodJob定时任务执行成功--------");
        // 获取传参，执行使用这种方式获取参数，无法用 方法参数 获取 定时任务参数
        String param = XxlJobHelper.getJobParam();
        System.out.println(param);

        // 设置任务执行失败
        // XxlJobHelper.handleFail("任务失败");

        // 设置任务执行成功，没有必要，默认就是成功
        // XxlJobHelper.handleSuccess("任务成功");

    }


    /**
     * 定义一个定时任务
     * 无法用 方法参数 获取 定时任务参数， param 是 null
     */
    @XxlJob("secondMethodJob")
    public void secondMethodJob(String param) {
        log.info("---------secondMethodJob定时任务执行成功--------");
        System.out.println(param);
    }

    /**
     * 生命周期任务示例：任务初始化与销毁时，支持自定义相关逻辑；
     * init 方法在job线程初始化后执行一次，除非job线程重新初始化或者有新线程要执行这个任务，否则不再执行
     * destory 方法在job线程销毁时执行，job线程一定时间内如果没有执行任务就会被销毁
     */
    @XxlJob(value = "thirdMethodJob", init = "init", destroy = "destroy")
    public void thirdMethodJob() throws Exception {
        log.info("thirdMethodJob");
    }

    public void init() {
        log.info("thirdMethodJob Init");
    }

    public void destroy() {
        log.info("thirdMethodJob Destroy");
    }


    /**
     * 分片广播任务：将一个大任务拆分成多个小任务，分别交给某个执行器的不同的服务去执行
     */
    @XxlJob("shardingJob")
    public void shardingJobHandler() throws Exception {

        // 分片参数
        // 当前服务的分片序号，从 0 开始
        int shardIndex = XxlJobHelper.getShardIndex();
        // 总共有多少分片
        int shardTotal = XxlJobHelper.getShardTotal();

        XxlJobHelper.log("分片参数：当前分片序号 = {}, 总分片数 = {}", shardIndex, shardTotal);

        // 假数据
        ArrayList<String> list = new ArrayList<>();
        list.add("zhangsan");
        list.add("李四");

        // 业务逻辑：通过自定义的逻辑判断当前分片是否要 执行/处理 某一部分数据
        for (String obj : list) {
            int index = obj.hashCode() % shardTotal;
            if (index == shardIndex) {
                XxlJobHelper.log("第 {} 片, 命中分片、开始处理", index);
                System.out.println(obj);
            } else {
                XxlJobHelper.log("第 {} 片, 未命中分片、忽略", index);
            }
        }
    }
}